import { Client } from 'ssh2';
import { ConnectionInfo, ConnectionAuth } from '@shared/types';

export interface SSHConnection {
  id: string;
  connectionId: string;
  client: Client;
  connected: boolean;
  shell?: any;
}

export class SSHService {
  private connections: Map<string, SSHConnection> = new Map();

  /**
   * 建立SSH连接
   */
  async connect(
    connection: ConnectionInfo,
    auth: ConnectionAuth,
    onData: (data: string) => void,
    onError: (error: Error) => void
  ): Promise<SSHConnection> {
    return new Promise((resolve, reject) => {
      const client = new Client();
      const connId = connection.id;

      // 连接配置
      const config: any = {
        host: connection.host,
        port: connection.port,
        username: auth.username,
        readyTimeout: (connection.timeout || 30) * 1000,
        keepaliveInterval: connection.keepAlive ? (connection.keepAliveInterval || 60) * 1000 : undefined,
      };

      // 认证配置
      if (auth.authType === 'password' && auth.password) {
        config.password = auth.password;
      } else if (auth.authType === 'key' && auth.privateKey) {
        config.privateKey = auth.privateKey;
        if (auth.keyPassword) {
          config.passphrase = auth.keyPassword;
        }
      } else if (auth.authType === 'keyboard-interactive') {
        config.tryKeyboard = true;
        config.onKeyboardInteractive = (
          name: string,
          instructions: string,
          lang: string,
          prompts: any[],
          finish: any
        ) => {
          // 键盘交互认证处理
          console.log('Keyboard-interactive auth required');
          // 这里可以扩展支持多因素认证
        };
      }

      // 连接成功
      client.on('ready', () => {
        console.log(`SSH connection established: ${connection.name}`);

        const sshConn: SSHConnection = {
          id: connId,
          connectionId: connection.id,
          client,
          connected: true,
        };

        this.connections.set(connId, sshConn);

        // 启动shell
        client.shell((err: Error, stream: any) => {
          if (err) {
            reject(err);
            return;
          }

          sshConn.shell = stream;

          // 处理数据
          stream.on('data', (data: Buffer) => {
            onData(data.toString());
          });

          // 处理错误
          stream.on('error', (err: Error) => {
            onError(err);
          });

          // 关闭事件
          stream.on('close', () => {
            console.log(`Shell closed for ${connection.name}`);
            this.disconnect(connId);
          });

          resolve(sshConn);
        });
      });

      // 错误处理
      client.on('error', (err: Error) => {
        console.error(`SSH connection error: ${err.message}`);
        reject(err);
      });

      // 关闭处理
      client.on('close', () => {
        console.log(`SSH connection closed: ${connection.name}`);
        this.connections.delete(connId);
      });

      // 开始连接
      client.connect(config);
    });
  }

  /**
   * 断开连接
   */
  disconnect(connectionId: string): void {
    const conn = this.connections.get(connectionId);
    if (conn) {
      if (conn.shell) {
        conn.shell.end();
      }
      conn.client.end();
      this.connections.delete(connectionId);
      console.log(`SSH connection disconnected: ${connectionId}`);
    }
  }

  /**
   * 发送数据到终端
   */
  sendData(connectionId: string, data: string): boolean {
    const conn = this.connections.get(connectionId);
    if (conn && conn.shell) {
      conn.shell.write(data);
      return true;
    }
    return false;
  }

  /**
   * 调整终端大小
   */
  resize(connectionId: string, cols: number, rows: number): boolean {
    const conn = this.connections.get(connectionId);
    if (conn && conn.shell) {
      conn.shell.setWindow(rows, cols, 0, 0);
      return true;
    }
    return false;
  }

  /**
   * 检查连接是否存在
   */
  isConnected(connectionId: string): boolean {
    const conn = this.connections.get(connectionId);
    return conn ? conn.connected : false;
  }

  /**
   * 获取连接
   */
  getConnection(connectionId: string): SSHConnection | undefined {
    return this.connections.get(connectionId);
  }

  /**
   * 断开所有连接
   */
  disconnectAll(): void {
    this.connections.forEach((conn) => {
      this.disconnect(conn.id);
    });
  }
}

// 单例实例
export const sshService = new SSHService();